//
let scene = null,
  camera = null,
  renderer = null,
  width = null,
  height = null;

let config = {
  isMobile: false,
  background: '#000'
};

const utils = {
  makeMesh(type, geometry, color) {
    let material;
    let mesh;
    if (type === 'lambert') {
      material = new THREE.MeshLambertMaterial({ color: color });
    } else if (type === 'phong') {
      material = new THREE.MeshPhongMaterial({ color: color });
    } else {
      console.error('unrecognized type!');
    }

    mesh = new THREE.Mesh(geometry, material);

    mesh.castShadow = true;
    mesh.receiveShadow = true;

    return mesh;
  },
  makeShape: function() {
    let shape;
    if (window.THREE && arguments.length) {
      let arry = arguments[0];
      shape = new THREE.Shape();
      shape.moveTo(arry[0][0], arry[0][1]);
      for (let i = 1; i < arry.length; i++) {
        shape.lineTo(arry[i][0], arry[i][1]);
      }
      if (arguments.length > 1) {
        for (let i = 1; i < arguments.length; i++) {
          let pathCoords = arguments[i];
          let path = new THREE.Path();
          path.moveTo(pathCoords[0][0], pathCoords[0][1]);
          for (let i = 1; i < pathCoords.length; i++) {
            path.lineTo(pathCoords[i][0], pathCoords[i][1]);
          }
          shape.holes.push(path);
        }
      }
      return shape;
    } else {
      console.error('Something wrong!');
    }
  },
  makeExtrudeGeometry: function(shape, amount) {
    let extrudeSetting = {
      steps: 1,
      amount: amount,
      bevelEnabled: false
    };
    let geometry = new THREE.ExtrudeBufferGeometry(shape, extrudeSetting);
    geometry.rotateX(-0.5 * Math.PI);
    return geometry;
  }
};
const textures = {
  window: function() {
    let canvas = document.createElement('canvas');
    let ctx = canvas.getContext('2d');

    canvas.width = 32;
    canvas.height = 32;

    let colors = {
      border: '#3c3443',
      top: '#9d94a7',
      bottom: '#796e8c'
    };

    ctx.fillStyle = colors.border;
    ctx.fillRect(0, 0, 32, 32);
    ctx.fillStyle = colors.top;
    ctx.fillRect(2, 2, 13, 13);
    ctx.fillStyle = colors.top;
    ctx.fillRect(17, 2, 13, 13);
    ctx.fillStyle = colors.bottom;
    ctx.fillRect(2, 17, 13, 13);
    ctx.fillStyle = colors.bottom;
    ctx.fillRect(17, 17, 13, 13);

    let canvasTexture = new THREE.Texture(canvas);
    canvasTexture.wrapS = THREE.RepeatWrapping;
    canvasTexture.wrapT = THREE.RepeatWrapping;
    canvasTexture.needsUpdate = true;

    return canvasTexture;
  }
};

function init() {
  width = window.innerWidth;
  height = window.innerHeight;
  window.scene = scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera(45, width / height, 1, 5000);

  camera.position.set(330, 330, 330); // 设置摄像机的位置
  camera.lookAt(scene.position); // 设置摄像机观察的方向

  // 新建一个渲染器
  renderer = new THREE.WebGLRenderer({
    antialias: true
  });

  // 渲染器大小
  renderer.setSize(width, height);

  // 背景色
  renderer.setClearColor(config.background);

  document.body.appendChild(renderer.domElement);

  let geometry = new THREE.BoxGeometry();
  let material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
  let cube = new THREE.Mesh(geometry, material);
  scene.add(cube);
  camera.position.z = 5;

  buildAuxSystem();
  buildLightSystem();
  buildBuilding();
  function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
  }
  animate();
}

// 添加控制器
function buildAuxSystem() {
  const gridHelper = new THREE.GridHelper(320, 32);
  scene.add(gridHelper);
  const controls = new THREE.OrbitControls(camera, renderer.domElement);
  controls.enableDamping = true;
  controls.dampingFactor = 0.25;
  controls.rotateSpeed = 0.35;
}

// 监测客户端
function checkUserAgent() {
  const n = navigator.userAgent;
  if (
    n.match(/Android/i) ||
    n.match(/webOS/i) ||
    n.match(/iPhone/i) ||
    n.match(/iPad/i) ||
    n.match(/iPod/i) ||
    n.match(/BlackBerry/i)
  ) {
    config.isMobile = true;
    camera.position.set(420, 420, 420);
    renderer.shadowMap.enabled = false;
  }
}

// 添加光照
function buildLightSystem() {
  if (!config.isMobile) {
    let directionalLight = new THREE.DirectionalLight(0xffffff, 1.1);
    directionalLight.position.set(300, 1000, 500);
    directionalLight.target.position.set(0, 0, 0);
    directionalLight.castShadow = true;
    let d = 300;
    directionalLight.shadow.camera = new THREE.OrthographicCamera(
      -d,
      d,
      d,
      -d,
      500,
      1600
    );
    directionalLight.shadow.bias = 0.0001;
    directionalLight.shadow.mapSize.width = directionalLight.shadow.mapSize.height = 1024;
    scene.add(directionalLight);
    let light = new THREE.AmbientLight(0xffffff, 0.3);
    scene.add(light);
  } else {
    let hemisphereLight = new THREE.HemisphereLight(0xffffff, 1);
    scene.add(hemisphereLight);
    let light = new THREE.AmbientLight(0xffffff, 0.15);
    scene.add(light);
  }
}

// 添加建筑物
function buildBuilding() {
  // 创建一个立方缓冲几何体
  const planeGeometry = new THREE.BoxBufferGeometry(320, 6, 320);
  const plane = utils.makeMesh('lambert', planeGeometry, 0x6f5f6a);
  plane.position.y = -3;
  scene.add(plane);

  var createHospital = function() {
    let hospital = new THREE.Object3D();
    let baseGeometry = new THREE.BoxBufferGeometry(180, 3, 140);
    let base = utils.makeMesh('lambert', baseGeometry, 0xffffff);
    base.position.y = 1;
    hospital.add(base);

    let frontMainCoords = [
      [-80, -30],
      [-80, 20],
      [50, 20],
      [50, 0],
      [20, -30],
      [-80, -30]
    ];
    let frontMainShape = utils.makeShape(frontMainCoords);
    let frontMainGeometry = utils.makeExtrudeGeometry(frontMainShape, 100);
    let frontMainMaterial = new THREE.MeshPhongMaterial({
      map: textures.window()
    });
    frontMainMaterial.map.repeat.set(0.1, 0.08);
    let frontMain = new THREE.Mesh(frontMainGeometry, frontMainMaterial);
    frontMain.castShadow = true;
    frontMain.receiveShadow = true;
    hospital.add(frontMain);

    return hospital;
  };
  var addHospital = function() {
    const hospital = createHospital();
    hospital.position.z = -20;
    scene.add(hospital);
  };
  addHospital();
}

window.onload = () => {
  checkUserAgent();
  init();
};
